package com.learn.demo.interceptor;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 责任链、拦截器模式Demo
 *
 * @author banjiawei
 * @date 2021/03/30
 */
public class InterceptorDemo {
    public static void main(String[] args) {
        InterceptorA interceptorA = new InterceptorA();
        InterceptorB interceptorB = new InterceptorB();
        InterceptorC interceptorC = new InterceptorC();
        InterceptorChain interceptorChain = new InterceptorChain();
        interceptorChain.addInterceptor(interceptorA);
        interceptorChain.addInterceptor(interceptorB);
        interceptorChain.addInterceptor(interceptorC);
        interceptorChain.pluginAll(new Object());
        interceptorChain.plugin(new Object());
    }
}

interface Interceptor {
    Object plugin(Object target);

    Object plugin(Object target, InterceptorChain chain);
}

@Slf4j
class InterceptorA implements Interceptor {

    @Override
    public Object plugin(Object target) {
        log.info("InterceptorA");
        return target;
    }

    @Override
    public Object plugin(Object target, InterceptorChain chain) {
        log.info("InterceptorA chain");
        return chain.plugin(target);
    }
}

@Slf4j
class InterceptorB implements Interceptor {

    @Override
    public Object plugin(Object target) {
        log.info("InterceptorB");
        return target;
    }

    @Override
    public Object plugin(Object target, InterceptorChain chain) {
        log.info("InterceptorB chain");
        return target;
    }
}

@Slf4j
class InterceptorC implements Interceptor {

    @Override
    public Object plugin(Object target) {
        log.info("InterceptorC");
        return target;
    }

    @Override
    public Object plugin(Object target, InterceptorChain chain) {
        log.info("InterceptorC chain");
        return chain.plugin(target);
    }
}

class InterceptorChain {
    private List<Interceptor> interceptors = new ArrayList<>();
    private Iterator<Interceptor> iterator;

    public void addInterceptor(Interceptor interceptor){
        interceptors.add(interceptor);
        iterator = interceptors.iterator();
    }

    public Object pluginAll(Object target) {
        for (Interceptor interceptor : interceptors) {
            target = interceptor.plugin(target);
        }
        return target;
    }

    public Object plugin(Object target) {
        if(iterator.hasNext()){
            Interceptor next = iterator.next();
            next.plugin(target, this);
        }
        return target;
    }
}